# -*- coding: utf-8 -*-
from typing import Sequence

from pydantic import EmailStr
from sqlalchemy import Select, select, and_
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload, noload
from sqlalchemy_crud_plus import CRUDPlus

from App.app.admin.models.sys_role import SysRole
# 动态导入模型和Schema
from App.app.admin.models.sys_user import SysUser
from App.app.admin.schemas.sys_user_schema import (
    CreateSysUserParam,
    UpdateSysUserParam, RegisterUserParam, UpdateMeParam
)
from App.common.order_by import apply_dynamic_sort
from App.common.security.jwt import get_hash_password
from App.utils.timezone import timezone


class CRUDSysUser(CRUDPlus[SysUser]):
    async def get(self, db: AsyncSession, pk: int) -> SysUser | None:
        """
        获取系统用户表

        :param db:
        :param pk:
        :return:
        """
        return await self.select_model(db, pk)

    async def get_by_username(self, db: AsyncSession, username: str) -> SysUser | None:
        """
        通过 username 获取用户

        :param db:
        :param username:
        :return:
        """
        return await self.select_model_by_column(db, username=username)

    async def get_list(self, nickname: str = None, username: str = None, phone: str = None,
                       status: str = None, role_id: str | int = None, sort_field: str = None,
                       sort_order: str = None) -> Select:
        """
        获取用户列表

        :param sort_order:
        :param sort_field:
        :param role_id:
        :param nickname:
        :param username:
        :param phone:
        :param status:
        :return:
        """
        stmt = (
            select(self.model)
            .options(
                selectinload(self.model.role).options(noload(SysRole.users), noload(SysRole.menus))
            )
        )
        where_list = []
        if status:
            where_list.append(self.model.status == int(status))
        if phone:
            where_list.append(self.model.phone.like(f'%{phone}%'))
        if nickname:
            where_list.append(self.model.nickname.like(f'%{nickname}%'))
        if username:
            where_list.append(self.model.username.like(f'%{username}%'))
        if role_id:
            where_list.append(self.model.role_id == int(role_id))
        if where_list:
            stmt = stmt.where(and_(*where_list))
        stmt = apply_dynamic_sort(stmt, self.model, sort_field=sort_field, sort_order=sort_order)
        # 打印最终 SQL
        # from sqlalchemy.dialects import postgresql
        # compiled = stmt.compile(
        #     dialect=postgresql.dialect(),
        #     compile_kwargs={"literal_binds": True}
        # )
        # print(f"[DEBUG] 最终 SQL:\n{str(compiled)}")
        return stmt

    async def get_all(self, db: AsyncSession) -> Sequence[SysUser]:
        """
        获取所有系统用户表

        :param db:
        :return:
        """
        return await self.select_models(db)

    async def register_user(self, db: AsyncSession, obj_in: RegisterUserParam) -> SysUser:
        """

        :param db:
        :param obj_in:
        :return:
        """
        obj_in.password = get_hash_password(obj_in.password)
        return await self.create_model(db, obj_in)

    async def create(self, db: AsyncSession, obj_in: CreateSysUserParam) -> SysUser:
        """
        创建系统用户表

        :param db:
        :param obj_in:
        :return:
        """
        obj_in.password = get_hash_password("123456")
        return await self.create_model(db, obj_in)

    async def update(self, db: AsyncSession, pk: int, obj_in: UpdateMeParam | UpdateSysUserParam) -> int:
        """
        更新系统用户表

        :param db:
        :param pk:
        :param obj_in:
        :return:
        """
        return await self.update_model(db, pk, obj_in)

    async def update_login_time(self, db: AsyncSession, username: str) -> int:
        """
        更新用户登录时间

        :param db:
        :param username:
        :return:
        """
        return await self.update_model_by_column(db, {'last_login_time': timezone.now()}, username=username)

    async def delete(self, db: AsyncSession, pk: int) -> int:
        """
        删除系统用户表

        :param db:
        :param pk:
        :return:
        """
        return await self.delete_model_by_column(db, allow_multiple=True, id=pk)

    async def logoff(self, db: AsyncSession, pk: int) -> int:
        """
        更新用户的删除标识

        :param db:
        :param pk:
        :return:
        """
        return await self.update_model_by_column(db, {'is_del': 1}, id=pk)

    async def check_email(self, db: AsyncSession, email: EmailStr) -> SysUser | None:
        """
        检查邮箱是否存在

        :param db:
        :param email:
        :return:
        """
        return await self.select_model_by_column(db, email=email)

    async def check_phone(self, db: AsyncSession, phone: str) -> SysUser | None:
        """
        检查手机是否存在

        :param db:
        :param phone:
        :return:
        """
        return await self.select_model_by_column(db, phone=phone)

    async def get_super(self, db: AsyncSession, pk: int):
        """
        获取用户超级管理员状态

        :param db:
        :param pk:
        :return:
        """
        user = await self.get(db, pk)
        return user.is_super

    async def set_super(self, db: AsyncSession, pk: int, _super: int) -> int:
        """
        设置用户超级管理员

        :param db:
        :param pk:
        :param _super:
        :return:
        """
        return await self.update_model(db, pk, {'is_super': _super})

    async def get_staff(self, db: AsyncSession, pk: int):
        """
        获取用户后台登录状态

        :param db:
        :param pk:
        :return:
        """
        user = await self.get(db, pk)
        return user.is_staff

    async def set_staff(self, db: AsyncSession, pk: int, staff: int) -> int:
        """
        设置用户后台登录

        :param db:
        :param pk:
        :param staff:
        :return:
        """
        return await self.update_model(db, pk, {'is_staff': staff})

    async def get_status(self, db: AsyncSession, pk: int):
        """
        获取用户状态

        :param db:
        :param pk:
        :return:
        """
        user = await self.get(db, pk)
        return user.status

    async def set_status(self, db: AsyncSession, pk: int, status: int) -> int:
        """
        设置用户状态

        :param db:
        :param pk:
        :param status:
        :return:
        """
        return await self.update_model(db, pk, {'status': status})

    async def get_multi_login(self, db: AsyncSession, pk: int):
        """
        获取用户多点登录状态

        :param db:
        :param pk:
        :return:
        """
        user = await self.get(db, pk)
        return user.is_multi_login

    async def set_multi_login(self, db: AsyncSession, pk: int, multi_login: int) -> int:
        """
        设置用户多点登录

        :param db:
        :param pk:
        :param multi_login:
        :return:
        """
        return await self.update_model(db, pk, {'is_multi_login': multi_login})

    async def reset_password(self, db: AsyncSession, pk: int, new_pwd: str) -> int:
        """
        重置用户密码

        :param db:
        :param pk:
        :param new_pwd:
        :return:
        """
        return await self.update_model(db, pk, {'password': new_pwd})

    async def get_with_role(self, db: AsyncSession, *, user_id: int = None, username: str = None) -> SysUser | None:
        """
        获取用户和角色
        :param db:
        :param user_id:
        :param username:
        :return:
        """
        stmt = select(self.model).options(
            selectinload(self.model.role).options(
                selectinload(SysRole.menus),
            ),
        )
        filters = []
        if user_id:
            filters.append(self.model.id == user_id)
        if username:
            filters.append(self.model.username == username)
        user = await db.execute(stmt.where(*filters))
        return user.scalars().first()


SysUserDao: CRUDSysUser = CRUDSysUser(SysUser)
